package com.wquick.base.camerax

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Matrix
import android.media.ExifInterface
import android.util.Rational
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.core.UseCaseGroup
import androidx.camera.core.ViewPort
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import java.io.File
import java.io.IOException


class CameraXHolder {

    var camera by mutableStateOf<Camera?>(null)

    fun setZoom(float: Float) {
        camera?.cameraControl?.setLinearZoom(float)
    }

    fun getCurrentZoomLiveData() = camera?.cameraInfo?.zoomState

    var imageCapture by mutableStateOf<ImageCapture?>(null)

    fun takePicture(
        context: Context,
        destImageFile: File,
        onStart: () -> Unit = {},
        onError: (Throwable) -> Unit = {},
        onSuccess: (File?) -> Unit,
    ) {
        onStart.invoke()
        if (imageCapture == null) {
            onError.invoke(Throwable("ImageCapture对象为空"))
            return
        }
        destImageFile.parentFile?.mkdirs()
        val executor = ContextCompat.getMainExecutor(context)
        val outputOptions = ImageCapture.OutputFileOptions
            .Builder(destImageFile)
            .build()
        val savedCallback = object : ImageCapture.OnImageSavedCallback {
            @SuppressLint("RestrictedApi")
            override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                onSuccess.invoke(outputOptions.file)
            }

            override fun onError(exception: ImageCaptureException) {
                exception.printStackTrace()
                onError.invoke(exception)
            }
        }
        imageCapture?.takePicture(outputOptions, executor, savedCallback)
    }

    /**
     * 提供相机对象
     * @param onProvide 提供回调方法
     */
    fun Context.provideCameraProvider(onProvide: (ProcessCameraProvider?) -> Unit) {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            var processCameraProvider: ProcessCameraProvider? = null
            try {
                processCameraProvider = cameraProviderFuture.get()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            onProvide.invoke(processCameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }

    /** 拍照功能绑定到生命周期 **/
    @SuppressLint("RestrictedApi")
    fun PreviewView.imageCapture(
        owner: LifecycleOwner,
        provider: ProcessCameraProvider?,
    ): ImageCapture {
        val viewPort = ViewPort.Builder(Rational(width, height), display.rotation).build()
        val preview = Preview.Builder()
            .setCameraSelector(CameraSelector.DEFAULT_BACK_CAMERA)
            .build()
            .also { it.setSurfaceProvider(surfaceProvider) }
        val cameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()
        val imageCapture = ImageCapture.Builder()
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
            .build()
        val useCaseGroup = UseCaseGroup.Builder()
            .addUseCase(preview)
            .addUseCase(imageCapture)
            .setViewPort(viewPort)
            .build()
        provider?.unbindAll() //防止相机未解绑而发生闪退
        provider?.bindToLifecycle(owner, cameraSelector, useCaseGroup)
        return imageCapture
    }


    /**
     * 读取图片属性：旋转的角度
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    fun readPictureDegree(path: String): Int {
        var degree = 0
        try {
            val exifInterface = ExifInterface(path)
            val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
                ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
                ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return degree
    }

    /**
     * 旋转图片
     * @param angle
     * @param bitmap
     * @return Bitmap
     */
    fun rotateBitmap(bitmap: Bitmap, angle: Int): Bitmap {
        // 旋转图片
        val matrix: Matrix = Matrix()
        matrix.postRotate(angle.toFloat())
        // 创建新的图片
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }

}